#include "include.h"

func_cb_t func_cb AT(.buf.func_cb);
void spdif_adj_karaok_sample_rate(void);
#if UART_S_UPDATE
bool deal_update_uart_msg(void);

#endif // UART_S_UPDATE
#if VBAT_DETECT_EN
AT(.text.func.msg)
void lowpower_vbat_process(void)
{
    int lpwr_vbat_sta = is_lowpower_vbat_warning();

    if (lpwr_vbat_sta == 1) {
        if (func_cb.mp3_res_play) {
            func_cb.mp3_res_play(RES_BUF_LOW_BATTERY_MP3, RES_LEN_LOW_BATTERY_MP3);
        }
        sys_cb.pwrdwn_tone_en = 1;
        func_cb.sta = FUNC_PWROFF;     //低电，进入关机或省电模式
        return;
    }
    if ((func_cb.mp3_res_play == NULL) || (lpwr_vbat_sta != 2)) {
        if ((sys_cb.lowbat_flag) && (sys_cb.vbat > 3800)) {
            sys_cb.vbat_nor_cnt++;
            if (sys_cb.vbat_nor_cnt > 40) {
                sys_cb.lowbat_flag = 0;
                sys_cb.lpwr_warning_times = LPWR_WARING_TIMES;
                plugin_lowbat_vol_recover();    //离开低电, 恢复音乐音量
            }
        }
        return;
    }

    //低电提示音播放
    sys_cb.vbat_nor_cnt = 0;
    if (sys_cb.lpwr_warning_cnt > xcfg_cb.lpwr_warning_period) {
        sys_cb.lpwr_warning_cnt = 0;
        if (sys_cb.lpwr_warning_times) {        //低电语音提示次数
#if RLED_LOWBAT_FOLLOW_EN
            if (xcfg_cb.rled_lowbat_follow_en) {
                led_lowbat_follow_warning();
            }
#endif

            sys_cb.lowbat_flag = 1;
            func_cb.mp3_res_play(RES_BUF_LOW_BATTERY_MP3, RES_LEN_LOW_BATTERY_MP3);
            plugin_lowbat_vol_reduce();         //低电降低音乐音量

#if RLED_LOWBAT_FOLLOW_EN
            if (xcfg_cb.rled_lowbat_follow_en) {
                while (get_led_sta(1)) {        //等待红灯闪完
                    delay_5ms(2);
                }
                led_lowbat_recover();
            }
#endif // RLED_LOWBAT_FOLLOW_EN

            if (sys_cb.lpwr_warning_times != 0xff) {
                sys_cb.lpwr_warning_times--;
            }
        }
    }
}
#endif // VBAT_DETECT_EN



#if BT_BACKSTAGE_PLAY_DETECT_EN
u32 btstack_play_tick = 0;
u32 btstack_pause_tick = 0;
u8 host_ctrl_play_sta = 0;
void bt_backstage_play_kick_start(u8 sta)
{
    if (sta) {
        if (!host_ctrl_play_sta) {
            host_ctrl_play_sta = 1;
            btstack_play_tick = tick_get();
        }
        btstack_pause_tick = tick_get();
    } else if (host_ctrl_play_sta) {
        if ((tick_check_expire(btstack_pause_tick, 500))) {
            host_ctrl_play_sta = 0;
            sys_cb.host_ctrl_play_sta = 0;
        } else if (tick_check_expire(btstack_play_tick, 2000)) {
            sys_cb.host_ctrl_play_sta = 1;
        }
    }
}


u8  get_bt_backstage_play_sta(void)
{
    return sys_cb.host_ctrl_play_sta;
}
#endif // BT_BACKSTAGE_PLAY_DETECT_EN


AT(.text.func.bt)
void printf_info(void)
{
    static u32 ticks = 0;
    if (tick_check_expire(ticks, 1000)) {
        ticks = tick_get();
        //        my_printf("karaok_echo_filter_en_get() = %d\n",karaok_echo_filter_en_get());
        //        my_printf("karaok_magic_howling_en_get() = %d\n",karaok_magic_howling_en_get());
        //        my_printf("--------------->\nDACVOLCON = 0x%X , AUANGCON3 = 0x%X,\n", DACVOLCON&0x7FFF,AUANGCON3&0x7F);
        //        my_printf("SRC0VOLCON = 0x%X, SRC1VOLCON = 0x%X\n",SRC0VOLCON&0x7FFF,SRC1VOLCON&0x7FFF);
        //        my_printf("AU0LMIXCOEF = 0x%X, AU0RMIXCOEF = 0x%X\n",AU0LMIXCOEF,AU0RMIXCOEF);
        //        my_printf("AU1LMIXCOEF = 0x%X, AU1RMIXCOEF = 0x%X\n",AU1LMIXCOEF,AU1RMIXCOEF);
        //        my_printf("DACDIGCON0 = 0x%X\n\n",DACDIGCON0);
    }
}

AT(.text.func.process)
void func_process(void)
{
    WDT_CLR();
    // WDT_DIS();
    //printf_info();
#if BT_2ACL_EN
    /*一拖二 点击手机播放可切换对应的手机播放 还需注释 avdtp_acl2_sbc_compare_buf 函数*/
    //    static u8 play_change_flag = 0;
    //    if(bt_play_data_check(750)){
    //        my_printf("1\n");
    //        if(!play_change_flag){
    //            play_change_flag = 1;
    //            bt_2acl_switch_music_play();
    //        }
    //    }else{
    //        play_change_flag = 0;
    //    }
#endif // BT_2ACL_EN
#if VBAT_DETECT_EN
    lowpower_vbat_process();
#endif // VBAT_DETECT_EN
#if BT_BACKSTAGE_EN
    if (func_cb.sta != FUNC_BT && !bt_is_testmode()) {
        func_bt_warning();
        uint status = bt_get_status();
#if BT_BACKSTAGE_PLAY_DETECT_EN
        if (bt_backstage_play_check(status, 2500)) { //  打开这个蓝牙后台，手机解锁不切回蓝牙模式
            if (status == BT_STA_PLAYING) {
                func_cb.sta_break = func_cb.sta;
                func_cb.sta = FUNC_BT;
            }
        }
#else
        if (status > BT_STA_PLAYING) {
            func_cb.sta_break = func_cb.sta;
            func_cb.sta = FUNC_BT;
        }

#endif
    }
#endif // BT_BACKSTAGE_EN

#if SYS_KARAOK_EN
    karaok_process();
#endif

#if LE_EN
    bsp_ble_process();
#endif

#if FOT_EN
    bsp_fot_process();
#endif

#if KARAOK_REC_EN
    spdif_adj_karaok_sample_rate();
#endif // SPF_REC_EN

}

void music_low_high_pass(u8 freq, u8 flag);
void music_bassboost_set(int gain, u8 freq);
//func common message process
AT(.text.func.msg)
void func_message(u16 msg)
{
#if LOWPASS_BASSBOOST_PHASE180_EN            //使用示例
    static u8 pass_en = 0;
    static u8 bass_en = 0;
#endif

    switch (msg) {
        case KL_NEXT_VOL_UP:
        case KH_NEXT_VOL_UP:
        case KL_VOL_UP:
        case KH_VOL_UP:
            sys_cb.maxvol_fade = 1;
        case KU_VOL_UP_NEXT:
        case KU_VOL_UP:
        case KU_VOL_NEXT_PREV:
#if LOWPASS_BASSBOOST_PHASE180_EN
            if (pass_en) {
                music_low_high_pass(6, 1);
                pass_en = 0;
            } else {
                music_low_high_pass(6, 0);
                pass_en = 1;
            }
            break;
#endif

#if SYS_MAGIC_VOICE_EN
            magic_voice_switch();
            break;
#endif

            if (msg == KU_VOL_NEXT_PREV) {
                //循环音量加, 最大音量后提示下, 然后从0开始。
                if (sys_cb.vol == VOL_MAX) {
                    bsp_set_volume(0);
                } else {
                    bsp_set_volume(bsp_volume_inc(sys_cb.vol));
                }
            } else {
                bsp_set_volume(bsp_volume_inc(sys_cb.vol));
            }
            if (func_cb.set_vol_callback) {
                func_cb.set_vol_callback(1);
            }
            bsp_bt_vol_change();
            my_printf("current volume: %d\n", sys_cb.vol);
#if WARNING_ADJ_VOLUME
            if (adjvol_tone_play()) {
                break;
            }
#endif
#if WARNING_MAX_VOLUME
            if (sys_cb.vol == VOL_MAX) {
                maxvol_tone_play();
                //sine_tone_play(90);
            }
#endif // WARNING_MAX_VOLUME
#if BT_APP_EN
            bsp_app_msc_play_sta(0, sys_cb.vol);
#endif
            break;

        case KLU_VOL_UP:
        case KLU_NEXT_VOL_UP:

            if (sys_cb.maxvol_fade == 2) {
                dac_fade_in();
            }
            sys_cb.maxvol_fade = 0;
            break;

        case KL_PREV_VOL_DOWN:
        case KH_PREV_VOL_DOWN:
        case KU_VOL_DOWN_PREV:
        case KU_VOL_DOWN:
        case KL_VOL_DOWN:
        case KH_VOL_DOWN:

#if LOWPASS_BASSBOOST_PHASE180_EN
            if (bass_en) {
                music_bassboost_set(5, 1);
                bass_en = 0;
            } else {
                music_bassboost_set(-5, 1);
                bass_en = 1;
            }
            break;
#endif
            /*魔音 变速测试临时借用 正常下屏蔽此类代码*/

#if AUDIO_STRETCH_EN
            stretch_voice_switch();
            break;
#endif
            bsp_set_volume(bsp_volume_dec(sys_cb.vol));
            if (func_cb.set_vol_callback) {
                func_cb.set_vol_callback(0);
            }
            bsp_bt_vol_change();
            my_printf("current volume: %d\n", sys_cb.vol);

#if WARNING_ADJ_VOLUME
            if (adjvol_tone_play()) {
                break;
            }
#endif
#if WARNING_MIN_VOLUME
            if (sys_cb.vol == 0) {
                if (func_cb.mp3_res_play) {
                    func_cb.mp3_res_play(RES_BUF_MAX_VOL_MP3, RES_LEN_MAX_VOL_MP3);
                }
            }
#endif // WARNING_MIN_VOLUME
#if BT_APP_EN
            bsp_app_msc_play_sta(0, sys_cb.vol);
#endif
            break;

        //长按PP/POWER软关机(通过PWROFF_PRESS_TIME控制长按时间)
        case KLH_PLAY_POWER:
        case KLH_MODE_POWER:
        case KLH_HSF_POWER:
        case KLH_POWER:
            sys_cb.pwrdwn_tone_en = 1;
            func_cb.sta = FUNC_PWROFF;
            break;

#if IRRX_HW_EN
        case KU_IR_POWER:
            func_cb.sta = FUNC_SLEEPMODE;
            break;
#endif

        case KU_MODE:
        case KU_MODE_POWER:
        case KL_PLAY_MODE:
            func_cb.sta = FUNC_NULL;
            break;

#if EQ_MODE_EN
        case KU_EQ:
            sys_set_eq();
            break;
#endif // EQ_MODE_EN

        case KU_MUTE:
            if (sys_cb.mute) {
                bsp_sys_unmute();
            } else {
                bsp_sys_mute();
            }
            break;

#if SYS_KARAOK_EN
        case KU_VOICE_RM:
            if (func_cb.sta == FUNC_MUSIC || func_cb.sta == FUNC_BT) {
                karaok_voice_rm_switch();
            }
            //            else{
            //                ext_rm_voice_en = !ext_rm_voice_en;
            //                if (ext_rm_voice_en) {   //如果是软件消人声打开,需要关掉硬件消人声
            //                    DACDIGCON0 &= ~BIT(7);  //关硬件消人声
            //                }
            //                my_printf("ext_rm_voice_en = %d\n",ext_rm_voice_en);
            //            }
            break;
#endif

#if SYS_MAGIC_VOICE_EN || AUDIO_STRETCH_EN
        case KL_VOICE_RM:

            break;
#endif // SYS_MAGIC_VOICE_EN

        case MSG_SYS_500MS:
            break;

#if MUSIC_UDISK_EN
        case EVT_UDISK_INSERT:
            if (dev_is_online(DEV_UDISK)) {
                if (dev_udisk_activation_try(1)) {  //加快检测时间可用dev_udisk_activation_try_ex(0,2)
                    my_printf("UDISK try OK, to FuncMusic\n");
                    sys_cb.cur_dev = DEV_UDISK;
                    func_cb.sta = FUNC_MUSIC;
                } else {
                    my_printf("UDISK try Fail\n");
                }
#if BT_APP_EN
                bsp_app_msc_send_dev_info();
#endif
            }
            break;
#endif // MUSIC_UDISK_EN

#if MUSIC_SDCARD_EN
        case EVT_SD_INSERT:
            if (dev_is_online(DEV_SDCARD)) {
                sys_cb.cur_dev = DEV_SDCARD;
                func_cb.sta = FUNC_MUSIC;
#if BT_APP_EN
                bsp_app_msc_send_dev_info();
#endif
            }
            break;
#endif // MUSIC_SDCARD_EN

#if MUSIC_SDCARD1_EN
        case EVT_SD1_INSERT:
            if (dev_is_online(DEV_SDCARD1)) {
                sys_cb.cur_dev = DEV_SDCARD1;
                func_cb.sta = FUNC_MUSIC;
            }
            break;
#endif // MUSIC_SDCARD1_EN

#if FUNC_USBDEV_EN || UDE_HID_BACKSTAGE_EN
        case EVT_PC_INSERT:
            if (dev_is_online(DEV_USBPC)) {
#if UDE_HID_BACKSTAGE_EN
                usb_device_enter(0x04);
#else
                func_cb.sta = FUNC_USBDEV;
#endif
            }
            break;

        case EVT_PC_REMOVE:
#if UDE_HID_BACKSTAGE_EN
            usb_device_exit();
#endif
            break;
#endif // FUNC_USBDEV_EN

#if LINEIN_DETECT_EN
        case EVT_LINEIN_INSERT:
            if (dev_is_online(DEV_LINEIN)) {
#if LINEIN_2_PWRDOWN_EN
                sys_cb.pwrdwn_tone_en = LINEIN_2_PWRDOWN_TONE_EN;
                func_cb.sta = FUNC_PWROFF;
#else
                func_cb.sta = FUNC_AUX;
#endif // LINEIN_2_PWRDOWN_EN
#if BT_APP_EN
                bsp_app_msc_send_dev_info();
#endif
            }
            break;
#endif // LINEIN_DETECT_EN


#if FUNC_HDMI_EN
        case EVT_HDMI_INSERT:
            if (dev_is_online(DEV_HDMI)) {
                func_cb.sta = FUNC_HDMI;
                bsp_hdmi_cec_init();
                cec_rx_start();   //提前开始接收，及时回电视ack信息
            }
            break;

        case EVT_HDMI_REMOVE:
            break;
#endif
        case EVT_TWS_SET_VOL:
#if WARNING_MAX_VOLUME
            if (sys_cb.vol == VOL_MAX) {
                maxvol_tone_play();
                msg_queue_clear();
            }
#endif // WARNING_MAX_VOLUME
        case EVT_A2DP_SET_VOL:
            if (bt_get_status() != BT_STA_INCALL) {
                //my_printf("change volume: %d\n", sys_cb.vol);
                bsp_change_volume(sys_cb.vol);
                gui_box_show_vol();
            }
            break;
        case EVT_BT_SCAN_START:
            if (bt_get_status() < BT_STA_SCANNING) {
                bt_scan_enable();
            }
            break;
#if EQ_DBG_IN_UART || EQ_DBG_IN_SPP
        case EVT_ONLINE_SET_EQ:
            eq_parse_cmd();
            break;
#endif
#if SYS_KARAOK_EN
        case EVT_ECHO_LEVEL:
            //            my_printf("echo level:%x\n", sys_cb.echo_level);
            bsp_echo_set_level();
            break;

        case EVT_MIC_VOL:
            //            my_printf("mic vol:%x\n", sys_cb.mic_vol);
            bsp_karaok_set_mic_volume();
            break;

        case EVT_MUSIC_VOL:
            //            my_printf("music vol:%x\n", sys_cb.music_vol);
            bsp_karaok_set_music_volume();
            break;
#endif
#if LANG_SELECT == LANG_EN_ZH
        case EVT_BT_SET_LANG_ID:
            param_lang_id_write();
            param_sync();
            break;
#endif

#if EQ_MODE_EN
        case EVT_BT_SET_EQ:
            music_set_eq_by_num(sys_cb.eq_mode);
            break;
#endif

#if MIC_DETECT_EN
        case EVT_MIC_INSERT:
#if MIC_DETECT_CONTROL_CHANNEL && FUNC_AUX_EN
            if (FUNC_AUX == func_cb.sta) {
                func_aux_stop();
                if (MIC_DETECT_CONTROL_CHANNEL_MIX >> 4) {
                    xcfg_cb.auxl_sel = MIC_DETECT_CONTROL_CHANNEL_L;
                    xcfg_cb.auxr_sel = 0;
                } else {
                    xcfg_cb.auxr_sel = MIC_DETECT_CONTROL_CHANNEL_L;
                    xcfg_cb.auxl_sel = 0;
                }
                func_aux_start();
                void aux_analog_channel_select(u8 channel);
                aux_analog_channel_select(MIC_DETECT_CONTROL_CHANNEL_MIX);
                aux_shorting_enable();
                bsp_karaok_init(AUDIO_PATH_KARAOK, FUNC_AUX);
#if AUX_REC_EN
                aux_rec_init();
#endif
                karaok_mic_detect_aux_gain_adjust();
            }
#endif // MIC_DETECT_CONTROL_CHANNEL && FUNC_AUX_EN
            karaok_mic_unmute();
            break;

        case EVT_MIC_REMOVE:
            karaok_mic_mute();
#if MIC_DETECT_CONTROL_CHANNEL && FUNC_AUX_EN
            if (FUNC_AUX == func_cb.sta) {
                dac_fade_out();
                bsp_karaok_exit(AUDIO_PATH_KARAOK);
                func_aux_stop();
                u8 get_aux_channel_test(void);
                aux_shorting_disable();
                xcfg_cb.auxr_sel = MIC_DETECT_CONTROL_CHANNEL_R;
                xcfg_cb.auxl_sel = MIC_DETECT_CONTROL_CHANNEL_L;
                func_aux_start();
#if AUX_REC_EN
                aux_rec_init();
#endif
                karaok_mic_detect_aux_gain_adjust();
            }
#endif // MIC_DETECT_CONTROL_CHANNEL
            break;
#endif

#if BT_TWS_AUTO_SWITCH
        case EVT_BT_TWS_SWITCH:
            bt_switch_exit();
            break;
#endif // BT_TWS_AUTO_SWITCH

#if IODM_TEST_MODE
        case EVT_BT_EMIT_NOTICE:
            bsp_bt_msg_handle();
            break;

        case EVT_SPP_CONNECT:
            bsp_spp_connect_handle();
            break;

        case EVT_IODM_TEST_MODE:
            // iodm_reveice_data_deal();
            my_printf("%s %d\n", __func__, __LINE__);
            iodm_reveice_data_handle();
            break;

        case EVT_SPP_DATA_REPORT:
            bsp_spp_data_handle();
            break;
         
#endif // IODM_TEST_MODE

#if UART_S_UPDATE
        case EVT_UART_UPDATE:
            if (deal_update_uart_msg()) {
                func_cb.sta = FUNC_NULL;
            }
            break;
#endif
    }

    //调节音量，3秒后写入flash
    if ((sys_cb.cm_vol_change) && (sys_cb.cm_times >= 6)) {
        sys_cb.cm_vol_change = 0;
        cm_sync();
    }
#if SD_SOFT_DETECT_EN
    sd_soft_cmd_detect(120);
#endif
}

///进入一个功能的总入口
AT(.text.func)
void func_enter(void)
{
    gui_box_clear();
    param_sync();
    reset_sleep_delay();
    reset_pwroff_delay();
    func_cb.mp3_res_play = NULL;
    func_cb.set_vol_callback = NULL;
    bsp_clr_mute_sta();
    sys_cb.voice_evt_brk_en = 1;    //播放提示音时，快速响应事件。
    AMPLIFIER_SEL_D();
#if SYS_KARAOK_EN
    karaok_voice_rm_disable();
    if (!reverb_func_is_en()) {
        bsp_karaok_echo_reset_buf(func_cb.sta);
    }
#endif
}

AT(.text.func)
void func_exit(void)
{
#if UART_S_UPDATE
    void uart_s_update(void);
    uart_s_update();
#endif // UART_S_UPDATE
    u8 func_num;
    u8 funcs_total = get_funcs_total();

    for (func_num = 0; func_num != funcs_total; func_num++) {
        if (func_cb.last == func_sort_table[func_num]) {
            break;
        }
    }
    func_num++;                                     //切换到下一个任务
    if (func_num >= funcs_total) {
        func_num = 0;
    }
    func_cb.sta = func_sort_table[func_num];        //新的任务
#if SYS_MODE_BREAKPOINT_EN
    param_sys_mode_write(func_cb.sta);
#endif // SYS_MODE_BREAKPOINT_EN
}

AT(.text.func)
void func_run(void)
{
    func_cb.sta = FUNC_BT;
    my_printf("%s\n", __func__);
    while (1) {
        func_enter();
        switch (func_cb.sta) {
#if FUNC_MUSIC_EN
            case FUNC_MUSIC:
                func_music();
                break;
#endif // FUNC_MUSIC_EN

#if FUNC_FMRX_EN
            case FUNC_FMRX:
                func_fmrx();
                break;
#endif // FUNC_FMRX_EN

#if FUNC_CLOCK_EN
            case FUNC_CLOCK:
                func_clock();
                break;
#endif // FUNC_CLOCK_EN

#if FUNC_BT_EN
            case FUNC_BT:
                func_bt();
                break;
#endif

#if FUNC_BTHID_EN
            case FUNC_BTHID:
                func_bthid();
                break;
#endif // FUNC_BTHID_EN

#if FUNC_AUX_EN
            case FUNC_AUX:
                func_aux();
                break;
#endif // FUNC_AUX_EN

#if FUNC_USBDEV_EN
            case FUNC_USBDEV:
                func_usbdev();
                break;
#endif

#if FUNC_SPDIF_EN
            case FUNC_SPDIF:
                func_spdif();
                break;
#endif // FUNC_SPDIF_EN

#if FUNC_FMAM_FREQ_EN
            case FUNC_FMAM_FREQ:
                func_fmam_freq();
                break;
#endif // FUNC_FMAM_FREQ_EN

#if FUNC_SPEAKER_EN
            case FUNC_SPEAKER:
                func_speaker();
                break;
#endif // FUNC_SPEAKER_EN

#if FUNC_I2S_EN
            case FUNC_I2S:
                func_i2s();
                break;
#endif // FUNC_I2S_EN

#if FUNC_IDLE_EN
            case FUNC_IDLE:
                func_idle();
                break;
#endif // FUNC_IDLE_EN

            case FUNC_PWROFF:
                func_pwroff(sys_cb.pwrdwn_tone_en);
                break;

            case FUNC_SLEEPMODE:
                func_sleepmode();
                break;

            case FUNC_PWROFFRUNRC:
                func_poweroff_runrc();
                break;

#if IODM_TEST_MODE
            case FUNC_BT_CBT:
                func_bt_cbt();
                break;

            case FUNC_BT_FCC:
                func_bt_fcc();
                break;
#endif // IODM_TEST_MODE

#if EX_SPIFLASH_SUPPORT
            case FUNC_EXSPIFLASH_MUSIC:
                func_exspifalsh_music();
                break;
#endif

#if MUSIC_HIDDEN_PLAY_EN
            case FUNC_HIDDEN_MUSIC:
                func_sd_hidden_music();
                break;
#endif

#if FUNC_HDMI_EN
            case FUNC_HDMI:
                func_hdmi();
                break;
#endif

            default:
                func_exit();
                break;
        }
    }
}
